// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.iso;

import java.util.ArrayList;
import java.util.Stack;
import zombie.characters.IsoGameCharacter;
import zombie.characters.IsoPlayer;
import zombie.characters.Moodles.MoodleType;
import zombie.core.PerformanceSettings;
import zombie.core.opengl.RenderSettings;
import zombie.core.skinnedmodel.DeadBodyAtlas;
import zombie.core.textures.ColorInfo;
import zombie.debug.DebugLog;
import zombie.inventory.InventoryItem;
import zombie.iso.SpriteDetails.IsoObjectType;
import zombie.iso.objects.IsoBarricade;
import zombie.iso.objects.IsoCurtain;
import zombie.iso.objects.IsoDoor;
import zombie.iso.objects.IsoGenerator;
import zombie.iso.objects.IsoLightSwitch;
import zombie.iso.objects.IsoThumpable;
import zombie.iso.objects.IsoWindow;
import zombie.iso.weather.ClimateManager;
import zombie.meta.Meta;
import zombie.network.GameClient;
import zombie.network.GameServer;
import zombie.vehicles.BaseVehicle;
import zombie.vehicles.VehicleLight;
import zombie.vehicles.VehiclePart;

public final class LightingJNI {
    public static final int ROOM_SPAWN_DIST = 50;
    public static boolean init = false;
    public static final int[][] ForcedVis = new int[][]{
        {-1, 0, -1, -1, 0, -1, 1, -1, 1, 0, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2},
        {-1, 1, -1, 0, -1, -1, 0, -1, 1, -1, -2, 0, -2, -1, -2, -2, -1, -2, 0, -2},
        {0, 1, -1, 1, -1, 0, -1, -1, 0, -1, -2, 2, -2, 1, -2, 0, -2, -1, -2, -2},
        {1, 1, 0, 1, -1, 1, -1, 0, -1, -1, 0, 2, -1, 2, -2, 2, -2, 1, -2, 0},
        {1, 0, 1, 1, 0, 1, -1, 1, -1, 0, 2, 2, 1, 2, 0, 2, -1, 2, -2, 2},
        {-1, 1, 0, 1, 1, 1, 1, 0, 1, -1, 2, 0, 2, 1, 2, 2, 1, 2, 0, 2},
        {0, 1, 1, 1, 1, 0, 1, -1, 0, -1, 2, -2, 2, -1, 2, 0, 2, 1, 2, 2},
        {-1, -1, 0, -1, 1, -1, 1, 0, 1, 1, 0, -2, 1, -2, 2, -2, 2, -1, 2, 0}
    };
    private static final ArrayList<IsoGameCharacter.TorchInfo> torches = new ArrayList();
    private static final ArrayList<IsoGameCharacter.TorchInfo> activeTorches = new ArrayList();
    private static final ArrayList<IsoLightSource> JNILights = new ArrayList();
    private static final int[] updateCounter = new int[4];
    private static boolean bWasElecShut = false;
    private static boolean bWasNight = false;
    private static final Vector2 tempVector2 = new Vector2();
    private static final int MAX_PLAYERS = 256;
    private static final int MAX_LIGHTS_PER_PLAYER = 4;
    private static final int MAX_LIGHTS_PER_VEHICLE = 10;
    private static final ArrayList<InventoryItem> tempItems = new ArrayList();

    public static void init() {
        if (!init) {
            String string = "";
            if ("1".equals(System.getProperty("zomboid.debuglibs.lighting"))) {
                DebugLog.log("***** Loading debug version of Lighting");
                string = "d";
            }

            try {
                if (System.getProperty("os.name").contains("OS X")) {
                    System.loadLibrary("Lighting");
                } else if (System.getProperty("os.name").startsWith("Win")) {
                    if (System.getProperty("sun.arch.data.model").equals("64")) {
                        System.loadLibrary("Lighting64" + string);
                    } else {
                        System.loadLibrary("Lighting32" + string);
                    }
                } else if (System.getProperty("sun.arch.data.model").equals("64")) {
                    System.loadLibrary("Lighting64");
                } else {
                    System.loadLibrary("Lighting32");
                }

                for (int _int = 0; _int < 4; _int++) {
                    updateCounter[_int] = -1;
                }

                configure(0.005F);
                init = true;
            } catch (UnsatisfiedLinkError unsatisfiedLinkError) {
                unsatisfiedLinkError.printStackTrace();

                try {
                    Thread.sleep(3000L);
                } catch (InterruptedException interruptedException) {
                }

                System.exit(1);
            }
        }
    }

    private static int getTorchIndexById(int int1) {
        for (int int0 = 0; int0 < torches.size(); int0++) {
            IsoGameCharacter.TorchInfo torchInfo = (IsoGameCharacter.TorchInfo)torches.get(int0);
            if (torchInfo.id == int1) {
                return int0;
            }
        }

        return -1;
    }

    private static void checkTorch(IsoPlayer isoPlayer, InventoryItem inventoryItem, int int1) {
        int int0 = getTorchIndexById(int1);
        IsoGameCharacter.TorchInfo torchInfo;
        if (int0 == -1) {
            torchInfo = IsoGameCharacter.TorchInfo.alloc();
            torches.add(torchInfo);
        } else {
            torchInfo = (IsoGameCharacter.TorchInfo)torches.get(int0);
        }

        torchInfo.set(isoPlayer, inventoryItem);
        if (torchInfo.id == 0) {
            torchInfo.id = int1;
        }

        updateTorch(
            torchInfo.id,
            torchInfo.x,
            torchInfo.y,
            torchInfo.z,
            torchInfo.angleX,
            torchInfo.angleY,
            torchInfo.dist,
            torchInfo.strength,
            torchInfo.bCone,
            torchInfo.dot,
            torchInfo.focusing
        );
        activeTorches.add(torchInfo);
    }

    private static int checkPlayerTorches(IsoPlayer isoPlayer, int int2) {
        ArrayList arrayList = tempItems;
        arrayList.clear();
        isoPlayer.getActiveLightItems(arrayList);
        int int0 = Math.min(arrayList.size(), 4);

        for (int int1 = 0; int1 < int0; int1++) {
            checkTorch(isoPlayer, (InventoryItem)arrayList.get(int1), int2 * 4 + int1 + 1);
        }

        return int0;
    }

    private static void clearPlayerTorches(int int3, int int1) {
        for (int int0 = int1; int0 < 4; int0++) {
            int int2 = int3 * 4 + int0 + 1;
            int int4 = getTorchIndexById(int2);
            if (int4 != -1) {
                IsoGameCharacter.TorchInfo torchInfo = (IsoGameCharacter.TorchInfo)torches.get(int4);
                removeTorch(torchInfo.id);
                torchInfo.id = 0;
                IsoGameCharacter.TorchInfo.release(torchInfo);
                torches.remove(int4);
                break;
            }
        }
    }

    private static void checkTorch(VehiclePart vehiclePart, int int1) {
        VehicleLight vehicleLight = vehiclePart.getLight();
        if (vehicleLight != null && vehicleLight.getActive()) {
            IsoGameCharacter.TorchInfo torchInfo0 = null;

            for (int int0 = 0; int0 < torches.size(); int0++) {
                torchInfo0 = (IsoGameCharacter.TorchInfo)torches.get(int0);
                if (torchInfo0.id == int1) {
                    break;
                }

                torchInfo0 = null;
            }

            if (torchInfo0 == null) {
                torchInfo0 = IsoGameCharacter.TorchInfo.alloc();
                torches.add(torchInfo0);
            }

            torchInfo0.set(vehiclePart);
            if (torchInfo0.id == 0) {
                torchInfo0.id = int1;
            }

            updateTorch(
                torchInfo0.id,
                torchInfo0.x,
                torchInfo0.y,
                torchInfo0.z,
                torchInfo0.angleX,
                torchInfo0.angleY,
                torchInfo0.dist,
                torchInfo0.strength,
                torchInfo0.bCone,
                torchInfo0.dot,
                torchInfo0.focusing
            );
            activeTorches.add(torchInfo0);
        } else {
            for (int int2 = 0; int2 < torches.size(); int2++) {
                IsoGameCharacter.TorchInfo torchInfo1 = (IsoGameCharacter.TorchInfo)torches.get(int2);
                if (torchInfo1.id == int1) {
                    removeTorch(torchInfo1.id);
                    torchInfo1.id = 0;
                    IsoGameCharacter.TorchInfo.release(torchInfo1);
                    torches.remove(int2--);
                }
            }
        }
    }

    private static void checkLights() {
        if (IsoWorld.instance.CurrentCell != null) {
            if (GameClient.bClient) {
                IsoGenerator.updateSurroundingNow();
            }

            boolean boolean0 = IsoWorld.instance.isHydroPowerOn();
            Stack stack = IsoWorld.instance.CurrentCell.getLamppostPositions();

            for (int int0 = 0; int0 < stack.size(); int0++) {
                IsoLightSource isoLightSource0 = (IsoLightSource)stack.get(int0);
                IsoChunk isoChunk = IsoWorld.instance.CurrentCell.getChunkForGridSquare(isoLightSource0.x, isoLightSource0.y, isoLightSource0.z);
                if (isoChunk != null && isoLightSource0.chunk != null && isoLightSource0.chunk != isoChunk) {
                    isoLightSource0.life = 0;
                }

                if (isoLightSource0.life != 0 && isoLightSource0.isInBounds()) {
                    if (isoLightSource0.bHydroPowered) {
                        if (isoLightSource0.switches.isEmpty()) {
                            assert false;

                            boolean boolean1 = boolean0;
                            if (!boolean0) {
                                IsoGridSquare isoGridSquare = IsoWorld.instance
                                    .CurrentCell
                                    .getGridSquare(isoLightSource0.x, isoLightSource0.y, isoLightSource0.z);
                                boolean1 = isoGridSquare != null && isoGridSquare.haveElectricity();
                            }

                            if (isoLightSource0.bActive != boolean1) {
                                isoLightSource0.bActive = boolean1;
                                zombie.GameTime.instance.lightSourceUpdate = 100.0F;
                            }
                        } else {
                            IsoLightSwitch isoLightSwitch0 = (IsoLightSwitch)isoLightSource0.switches.get(0);
                            boolean boolean2 = isoLightSwitch0.canSwitchLight();
                            if (isoLightSwitch0.bStreetLight && zombie.GameTime.getInstance().getNight() < 0.5F) {
                                boolean2 = false;
                            }

                            if (isoLightSource0.bActive && !boolean2) {
                                isoLightSource0.bActive = false;
                                zombie.GameTime.instance.lightSourceUpdate = 100.0F;
                            } else if (!isoLightSource0.bActive && boolean2 && isoLightSwitch0.isActivated()) {
                                isoLightSource0.bActive = true;
                                zombie.GameTime.instance.lightSourceUpdate = 100.0F;
                            }
                        }
                    }

                    if (isoLightSource0.ID == 0) {
                        isoLightSource0.ID = IsoLightSource.NextID++;
                        if (isoLightSource0.life != -1) {
                            addTempLight(
                                isoLightSource0.ID,
                                isoLightSource0.x,
                                isoLightSource0.y,
                                isoLightSource0.z,
                                isoLightSource0.radius,
                                isoLightSource0.r,
                                isoLightSource0.g,
                                isoLightSource0.b,
                                (int)((float)(isoLightSource0.life * PerformanceSettings.getLockFPS()) / 30.0F)
                            );
                            stack.remove(int0--);
                        } else {
                            isoLightSource0.rJNI = isoLightSource0.r;
                            isoLightSource0.gJNI = isoLightSource0.g;
                            isoLightSource0.bJNI = isoLightSource0.b;
                            isoLightSource0.bActiveJNI = isoLightSource0.bActive;
                            JNILights.add(isoLightSource0);
                            addLight(
                                isoLightSource0.ID,
                                isoLightSource0.x,
                                isoLightSource0.y,
                                isoLightSource0.z,
                                isoLightSource0.radius,
                                isoLightSource0.r,
                                isoLightSource0.g,
                                isoLightSource0.b,
                                isoLightSource0.localToBuilding == null ? -1 : isoLightSource0.localToBuilding.ID,
                                isoLightSource0.bActive
                            );
                        }
                    } else {
                        if (isoLightSource0.r != isoLightSource0.rJNI || isoLightSource0.g != isoLightSource0.gJNI || isoLightSource0.b != isoLightSource0.bJNI
                            )
                         {
                            isoLightSource0.rJNI = isoLightSource0.r;
                            isoLightSource0.gJNI = isoLightSource0.g;
                            isoLightSource0.bJNI = isoLightSource0.b;
                            setLightColor(isoLightSource0.ID, isoLightSource0.r, isoLightSource0.g, isoLightSource0.b);
                        }

                        if (isoLightSource0.bActiveJNI != isoLightSource0.bActive) {
                            isoLightSource0.bActiveJNI = isoLightSource0.bActive;
                            setLightActive(isoLightSource0.ID, isoLightSource0.bActive);
                        }
                    }
                } else {
                    stack.remove(int0);
                    if (isoLightSource0.ID != 0) {
                        int int1 = isoLightSource0.ID;
                        isoLightSource0.ID = 0;
                        JNILights.remove(isoLightSource0);
                        removeLight(int1);
                        zombie.GameTime.instance.lightSourceUpdate = 100.0F;
                    }

                    int0--;
                }
            }

            for (int int2 = 0; int2 < JNILights.size(); int2++) {
                IsoLightSource isoLightSource1 = (IsoLightSource)JNILights.get(int2);
                if (!stack.contains(isoLightSource1)) {
                    int int3 = isoLightSource1.ID;
                    isoLightSource1.ID = 0;
                    JNILights.remove(int2--);
                    removeLight(int3);
                }
            }

            ArrayList arrayList0 = IsoWorld.instance.CurrentCell.roomLights;

            for (int int4 = 0; int4 < arrayList0.size(); int4++) {
                IsoRoomLight isoRoomLight = (IsoRoomLight)arrayList0.get(int4);
                if (!isoRoomLight.isInBounds()) {
                    arrayList0.remove(int4--);
                    if (isoRoomLight.ID != 0) {
                        int int5 = isoRoomLight.ID;
                        isoRoomLight.ID = 0;
                        removeRoomLight(int5);
                        zombie.GameTime.instance.lightSourceUpdate = 100.0F;
                    }
                } else {
                    isoRoomLight.bActive = isoRoomLight.room.def.bLightsActive;
                    if (!boolean0) {
                        boolean boolean3 = false;

                        for (int int6 = 0; !boolean3 && int6 < isoRoomLight.room.lightSwitches.size(); int6++) {
                            IsoLightSwitch isoLightSwitch1 = (IsoLightSwitch)isoRoomLight.room.lightSwitches.get(int6);
                            if (isoLightSwitch1.square != null && isoLightSwitch1.square.haveElectricity()) {
                                boolean3 = true;
                            }
                        }

                        if (!boolean3 && isoRoomLight.bActive) {
                            isoRoomLight.bActive = false;
                            if (isoRoomLight.bActiveJNI) {
                                IsoGridSquare.RecalcLightTime = -1;
                                zombie.GameTime.instance.lightSourceUpdate = 100.0F;
                            }
                        } else if (boolean3 && isoRoomLight.bActive && !isoRoomLight.bActiveJNI) {
                            IsoGridSquare.RecalcLightTime = -1;
                            zombie.GameTime.instance.lightSourceUpdate = 100.0F;
                        }
                    }

                    if (isoRoomLight.ID == 0) {
                        isoRoomLight.ID = 100000 + IsoRoomLight.NextID++;
                        addRoomLight(
                            isoRoomLight.ID,
                            isoRoomLight.room.building.ID,
                            isoRoomLight.room.def.ID,
                            isoRoomLight.x,
                            isoRoomLight.y,
                            isoRoomLight.z,
                            isoRoomLight.width,
                            isoRoomLight.height,
                            isoRoomLight.bActive
                        );
                        isoRoomLight.bActiveJNI = isoRoomLight.bActive;
                        zombie.GameTime.instance.lightSourceUpdate = 100.0F;
                    } else if (isoRoomLight.bActiveJNI != isoRoomLight.bActive) {
                        setRoomLightActive(isoRoomLight.ID, isoRoomLight.bActive);
                        isoRoomLight.bActiveJNI = isoRoomLight.bActive;
                        zombie.GameTime.instance.lightSourceUpdate = 100.0F;
                    }
                }
            }

            activeTorches.clear();
            if (GameClient.bClient) {
                ArrayList arrayList1 = GameClient.instance.getPlayers();

                for (int int7 = 0; int7 < arrayList1.size(); int7++) {
                    IsoPlayer isoPlayer0 = (IsoPlayer)arrayList1.get(int7);
                    checkPlayerTorches(isoPlayer0, isoPlayer0.OnlineID + 1);
                }
            } else {
                for (int int8 = 0; int8 < IsoPlayer.numPlayers; int8++) {
                    IsoPlayer isoPlayer1 = IsoPlayer.players[int8];
                    if (isoPlayer1 != null && !isoPlayer1.isDead() && isoPlayer1.getVehicle() == null) {
                        int int9 = checkPlayerTorches(isoPlayer1, int8);
                        clearPlayerTorches(int8, int9);
                    } else {
                        clearPlayerTorches(int8, 0);
                    }
                }
            }

            for (int int10 = 0; int10 < IsoWorld.instance.CurrentCell.getVehicles().size(); int10++) {
                BaseVehicle baseVehicle = (BaseVehicle)IsoWorld.instance.CurrentCell.getVehicles().get(int10);
                if (baseVehicle.VehicleID != -1) {
                    for (int int11 = 0; int11 < baseVehicle.getLightCount(); int11++) {
                        VehiclePart vehiclePart = baseVehicle.getLightByIndex(int11);
                        checkTorch(vehiclePart, 1024 + baseVehicle.VehicleID * 10 + int11);
                    }
                }
            }

            for (int int12 = 0; int12 < torches.size(); int12++) {
                IsoGameCharacter.TorchInfo torchInfo = (IsoGameCharacter.TorchInfo)torches.get(int12);
                if (!activeTorches.contains(torchInfo)) {
                    removeTorch(torchInfo.id);
                    torchInfo.id = 0;
                    IsoGameCharacter.TorchInfo.release(torchInfo);
                    torches.remove(int12--);
                }
            }
        }
    }

    public static float calculateVisionCone(IsoGameCharacter player) {
        float _float;
        if (player.getVehicle() == null) {
            _float = -0.2F;
            _float -= player.getStats().fatigue - 0.6F;
            if (_float > -0.2F) {
                _float = -0.2F;
            }

            if (player.getStats().fatigue >= 1.0F) {
                _float -= 0.2F;
            }

            if (player.getMoodles().getMoodleLevel(MoodleType.Panic) == 4) {
                _float -= 0.2F;
            }

            if (player.isInARoom()) {
                _float -= 0.2F * (1.0F - ClimateManager.getInstance().getDayLightStrength());
            } else {
                _float -= 0.7F * (1.0F - ClimateManager.getInstance().getDayLightStrength());
            }

            if (_float < -0.9F) {
                _float = -0.9F;
            }

            if (player.Traits.EagleEyed.isSet()) {
                _float += 0.2F * ClimateManager.getInstance().getDayLightStrength();
            }

            if (player.Traits.NightVision.isSet()) {
                _float += 0.2F * (1.0F - ClimateManager.getInstance().getDayLightStrength());
            }

            if (_float > 0.0F) {
                _float = 0.0F;
            }
        } else {
            if (player.getVehicle().getHeadlightsOn() && player.getVehicle().getHeadlightCanEmmitLight()) {
                _float = 0.8F - 3.0F * (1.0F - ClimateManager.getInstance().getDayLightStrength());
                if (_float < -0.8F) {
                    _float = -0.8F;
                }
            } else {
                _float = 0.8F - 3.0F * (1.0F - ClimateManager.getInstance().getDayLightStrength());
                if (_float < -0.95F) {
                    _float = -0.95F;
                }
            }

            if (player.Traits.NightVision.isSet()) {
                _float += 0.2F * (1.0F - ClimateManager.getInstance().getDayLightStrength());
            }

            if (_float > 1.0F) {
                _float = 1.0F;
            }
        }

        return _float;
    }

    public static void updatePlayer(int playerIndex) {
        IsoPlayer isoPlayer = IsoPlayer.players[playerIndex];
        if (isoPlayer != null) {
            float float0 = isoPlayer.getStats().fatigue - 0.6F;
            if (float0 < 0.0F) {
                float0 = 0.0F;
            }

            float0 *= 2.5F;
            if (isoPlayer.Traits.HardOfHearing.isSet() && float0 < 0.7F) {
                float0 = 0.7F;
            }

            float float1 = 2.0F;
            if (isoPlayer.Traits.KeenHearing.isSet()) {
                float1 += 3.0F;
            }

            float float2 = calculateVisionCone(isoPlayer);
            Vector2 vector2 = isoPlayer.getLookVector(tempVector2);
            BaseVehicle baseVehicle = isoPlayer.getVehicle();
            if (baseVehicle != null
                && !isoPlayer.isAiming()
                && !isoPlayer.isLookingWhileInVehicle()
                && baseVehicle.isDriver(isoPlayer)
                && baseVehicle.getCurrentSpeedKmHour() < -1.0F) {
                vector2.rotate((float) Math.PI);
            }

            playerSet(
                isoPlayer.x,
                isoPlayer.y,
                isoPlayer.z,
                vector2.x,
                vector2.y,
                false,
                isoPlayer.ReanimatedCorpse != null,
                isoPlayer.isGhostMode(),
                isoPlayer.Traits.ShortSighted.isSet(),
                float0,
                float1,
                float2
            );
        }
    }

    public static void updateChunk(IsoChunk mchunk) {
        chunkBeginUpdate(mchunk.wx, mchunk.wy);

        for (int int0 = 0; int0 < IsoCell.MaxHeight; int0++) {
            for (int int1 = 0; int1 < 10; int1++) {
                for (int int2 = 0; int2 < 10; int2++) {
                    IsoGridSquare isoGridSquare = mchunk.getGridSquare(int2, int1, int0);
                    if (isoGridSquare == null) {
                        squareSetNull(int2, int1, int0);
                    } else {
                        squareBeginUpdate(int2, int1, int0);
                        int int3 = isoGridSquare.visionMatrix;
                        boolean boolean0 = isoGridSquare.Has(IsoObjectType.stairsTN)
                            || isoGridSquare.Has(IsoObjectType.stairsMN)
                            || isoGridSquare.Has(IsoObjectType.stairsTW)
                            || isoGridSquare.Has(IsoObjectType.stairsMW);
                        squareSet(
                            isoGridSquare.w != null,
                            isoGridSquare.n != null,
                            isoGridSquare.e != null,
                            isoGridSquare.s != null,
                            boolean0,
                            int3,
                            isoGridSquare.getRoom() != null ? isoGridSquare.getBuilding().ID : -1,
                            isoGridSquare.getRoomID()
                        );

                        for (int int4 = 0; int4 < isoGridSquare.getSpecialObjects().size(); int4++) {
                            IsoObject isoObject = (IsoObject)isoGridSquare.getSpecialObjects().get(int4);
                            if (isoObject instanceof IsoCurtain) {
                                IsoCurtain isoCurtain = (IsoCurtain)isoObject;
                                byte _byte = 0;
                                if (isoCurtain.getType() == IsoObjectType.curtainW) {
                                    _byte |= 4;
                                } else if (isoCurtain.getType() == IsoObjectType.curtainN) {
                                    _byte |= 8;
                                } else if (isoCurtain.getType() == IsoObjectType.curtainE) {
                                    _byte |= 16;
                                } else if (isoCurtain.getType() == IsoObjectType.curtainS) {
                                    _byte |= 32;
                                }

                                squareAddCurtain(_byte, isoCurtain.open);
                            } else if (isoObject instanceof IsoDoor) {
                                IsoDoor isoDoor = (IsoDoor)isoObject;
                                boolean boolean1 = isoDoor.sprite != null && isoDoor.sprite.getProperties().Is("doorTrans");
                                if (isoDoor.open) {
                                    boolean1 = true;
                                } else {
                                    boolean1 = boolean1 && (isoDoor.HasCurtains() == null || isoDoor.isCurtainOpen());
                                }

                                IsoBarricade isoBarricade0 = isoDoor.getBarricadeOnSameSquare();
                                IsoBarricade isoBarricade1 = isoDoor.getBarricadeOnOppositeSquare();
                                if (isoBarricade0 != null && isoBarricade0.isBlockVision()) {
                                    boolean1 = false;
                                }

                                if (isoBarricade1 != null && isoBarricade1.isBlockVision()) {
                                    boolean1 = false;
                                }

                                if (isoDoor.IsOpen() && IsoDoor.getGarageDoorIndex(isoDoor) != -1) {
                                    boolean1 = true;
                                }

                                squareAddDoor(isoDoor.north, isoDoor.open, boolean1);
                            } else if (isoObject instanceof IsoThumpable) {
                                IsoThumpable isoThumpable0 = (IsoThumpable)isoObject;
                                boolean boolean2 = isoThumpable0.getSprite().getProperties().Is("doorTrans");
                                if (isoThumpable0.isDoor && isoThumpable0.open) {
                                    boolean2 = true;
                                }

                                squareAddThumpable(isoThumpable0.north, isoThumpable0.open, isoThumpable0.isDoor, boolean2);
                                IsoThumpable isoThumpable1 = (IsoThumpable)isoObject;
                                boolean boolean3 = false;
                                IsoBarricade isoBarricade2 = isoThumpable1.getBarricadeOnSameSquare();
                                IsoBarricade isoBarricade3 = isoThumpable1.getBarricadeOnOppositeSquare();
                                if (isoBarricade2 != null) {
                                    boolean3 |= isoBarricade2.isBlockVision();
                                }

                                if (isoBarricade3 != null) {
                                    boolean3 |= isoBarricade3.isBlockVision();
                                }

                                squareAddWindow(isoThumpable1.north, isoThumpable1.open, boolean3);
                            } else if (isoObject instanceof IsoWindow) {
                                IsoWindow isoWindow = (IsoWindow)isoObject;
                                boolean boolean4 = false;
                                IsoBarricade isoBarricade4 = isoWindow.getBarricadeOnSameSquare();
                                IsoBarricade isoBarricade5 = isoWindow.getBarricadeOnOppositeSquare();
                                if (isoBarricade4 != null) {
                                    boolean4 |= isoBarricade4.isBlockVision();
                                }

                                if (isoBarricade5 != null) {
                                    boolean4 |= isoBarricade5.isBlockVision();
                                }

                                squareAddWindow(isoWindow.north, isoWindow.open, boolean4);
                            }
                        }

                        squareEndUpdate();
                    }
                }
            }
        }

        chunkEndUpdate();
    }

    public static void update() {
        if (IsoWorld.instance != null && IsoWorld.instance.CurrentCell != null) {
            checkLights();
            zombie.GameTime gameTime = zombie.GameTime.getInstance();
            RenderSettings renderSettings = RenderSettings.getInstance();
            boolean boolean0 = IsoWorld.instance.isHydroPowerOn();
            boolean boolean1 = zombie.GameTime.getInstance().getNight() < 0.5F;
            if (boolean0 != bWasElecShut || boolean1 != bWasNight) {
                bWasElecShut = boolean0;
                bWasNight = boolean1;
                IsoGridSquare.RecalcLightTime = -1;
                gameTime.lightSourceUpdate = 100.0F;
            }

            for (int int0 = 0; int0 < IsoPlayer.numPlayers; int0++) {
                IsoChunkMap isoChunkMap = IsoWorld.instance.CurrentCell.ChunkMap[int0];
                if (isoChunkMap != null && !isoChunkMap.ignore) {
                    RenderSettings.PlayerRenderSettings playerRenderSettings = renderSettings.getPlayerSettings(int0);
                    stateBeginUpdate(int0, isoChunkMap.getWorldXMin(), isoChunkMap.getWorldYMin(), IsoChunkMap.ChunkGridWidth, IsoChunkMap.ChunkGridWidth);
                    updatePlayer(int0);
                    stateEndFrame(
                        playerRenderSettings.getRmod(),
                        playerRenderSettings.getGmod(),
                        playerRenderSettings.getBmod(),
                        playerRenderSettings.getAmbient(),
                        playerRenderSettings.getNight(),
                        playerRenderSettings.getViewDistance(),
                        gameTime.getViewDistMax(),
                        LosUtil.cachecleared[int0],
                        gameTime.lightSourceUpdate
                    );
                    if (LosUtil.cachecleared[int0]) {
                        LosUtil.cachecleared[int0] = false;
                        IsoWorld.instance.CurrentCell.invalidatePeekedRoom(int0);
                    }

                    for (int int1 = 0; int1 < IsoChunkMap.ChunkGridWidth; int1++) {
                        for (int int2 = 0; int2 < IsoChunkMap.ChunkGridWidth; int2++) {
                            IsoChunk isoChunk = isoChunkMap.getChunk(int2, int1);
                            if (isoChunk != null && isoChunk.lightCheck[int0]) {
                                updateChunk(isoChunk);
                                isoChunk.lightCheck[int0] = false;
                            }

                            if (isoChunk != null) {
                                isoChunk.bLightingNeverDone[int0] = !chunkLightingDone(isoChunk.wx, isoChunk.wy);
                            }
                        }
                    }

                    stateEndUpdate();
                    updateCounter[int0] = stateUpdateCounter(int0);
                    if (gameTime.lightSourceUpdate > 0.0F && IsoPlayer.players[int0] != null) {
                        IsoPlayer.players[int0].dirtyRecalcGridStackTime = 20.0F;
                    }
                }
            }

            DeadBodyAtlas.instance.lightingUpdate(updateCounter[0], gameTime.lightSourceUpdate > 0.0F);
            gameTime.lightSourceUpdate = 0.0F;
        }
    }

    public static void getTorches(ArrayList<IsoGameCharacter.TorchInfo> out) {
        out.addAll(torches);
    }

    public static void stop() {
        torches.clear();
        JNILights.clear();
        destroy();

        for (int _int = 0; _int < updateCounter.length; _int++) {
            updateCounter[_int] = -1;
        }

        bWasElecShut = false;
        bWasNight = false;
        IsoLightSource.NextID = 1;
        IsoRoomLight.NextID = 1;
    }

    public static native void configure(float darkStep);

    public static native void scrollLeft(int _playerIndex);

    public static native void scrollRight(int _playerIndex);

    public static native void scrollUp(int _playerIndex);

    public static native void scrollDown(int _playerIndex);

    public static native void stateBeginUpdate(int _playerIndex, int minX, int minY, int width, int height);

    public static native void stateEndFrame(
        float rmod, float gmod, float bmod, float ambient, float night, float viewDist, float viewDistMax, boolean cacheCleared, float lightSourceUpdate
    );

    public static native void stateEndUpdate();

    public static native int stateUpdateCounter(int _playerIndex);

    public static native void teleport(int _playerIndex, int wx, int wy);

    public static native void DoLightingUpdateNew(long time);

    public static native boolean WaitingForMain();

    public static native void playerSet(
        float x,
        float y,
        float z,
        float angleX,
        float angleY,
        boolean isDead,
        boolean ReanimatedCorpse,
        boolean GhostMode,
        boolean ShortSighted,
        float tireddel,
        float ndist,
        float cone
    );

    public static native boolean chunkLightingDone(int wx, int wy);

    public static native void chunkBeginUpdate(int wx, int wy);

    public static native void chunkEndUpdate();

    public static native void squareSetNull(int x, int y, int z);

    public static native void squareBeginUpdate(int x, int y, int z);

    public static native void squareSet(
        boolean hasW, boolean hasN, boolean hasE, boolean hasS, boolean hasElevatedFloor, int visionMatrix, int buildingID, int roomID
    );

    public static native void squareAddCurtain(int wnes, boolean open);

    public static native void squareAddDoor(boolean north, boolean open, boolean trans);

    public static native void squareAddThumpable(boolean north, boolean open, boolean isDoor, boolean canPassThrough);

    public static native void squareAddWindow(boolean north, boolean open, boolean opaque);

    public static native void squareEndUpdate();

    public static native int getVertLight(int _playerIndex, int x, int y, int z, int i);

    public static native float getLightInfo(int _playerIndex, int x, int y, int z, int rgb);

    public static native float getDarkMulti(int _playerIndex, int x, int y, int z);

    public static native float getTargetDarkMulti(int _playerIndex, int x, int y, int z);

    public static native boolean getSeen(int _playerIndex, int x, int y, int z);

    public static native boolean getCanSee(int _playerIndex, int x, int y, int z);

    public static native boolean getCouldSee(int _playerIndex, int x, int y, int z);

    public static native boolean getSquareLighting(int var0, int var1, int var2, int var3, int[] var4);

    public static native void addLight(int id, int x, int y, int z, int radius, float r, float g, float b, int buildingID, boolean active);

    public static native void addTempLight(int id, int x, int y, int z, int radius, float r, float g, float b, int life);

    public static native void removeLight(int id);

    public static native void setLightActive(int id, boolean active);

    public static native void setLightColor(int id, float r, float g, float b);

    public static native void addRoomLight(int id, int buildingID, int roomID, int x, int y, int z, int width, int height, boolean active);

    public static native void removeRoomLight(int id);

    public static native void setRoomLightActive(int id, boolean active);

    public static native void updateTorch(
        int id, float x, float y, float z, float angleX, float angleY, float dist, float strength, boolean bCone, float dot, int focusing
    );

    public static native void removeTorch(int id);

    public static native void destroy();

    public static final class JNILighting implements IsoGridSquare.ILighting {
        private static final int RESULT_LIGHTS_PER_SQUARE = 5;
        private static final int[] lightInts = new int[43];
        private static final byte VIS_SEEN = 1;
        private static final byte VIS_CAN_SEE = 2;
        private static final byte VIS_COULD_SEE = 4;
        private int playerIndex;
        private final IsoGridSquare square;
        private ColorInfo lightInfo = new ColorInfo();
        private byte vis;
        private float cacheDarkMulti;
        private float cacheTargetDarkMulti;
        private int[] cacheVertLight;
        private int updateTick = -1;
        private int lightsCount;
        private IsoGridSquare.ResultLight[] lights;

        public JNILighting(int _playerIndex, IsoGridSquare _square) {
            this.playerIndex = _playerIndex;
            this.square = _square;
            this.cacheDarkMulti = 0.0F;
            this.cacheTargetDarkMulti = 0.0F;
            this.cacheVertLight = new int[8];

            for (int _int = 0; _int < 8; _int++) {
                this.cacheVertLight[_int] = 0;
            }
        }

        @Override
        public int lightverts(int i) {
            return this.cacheVertLight[i];
        }

        @Override
        public float lampostTotalR() {
            return 0.0F;
        }

        @Override
        public float lampostTotalG() {
            return 0.0F;
        }

        @Override
        public float lampostTotalB() {
            return 0.0F;
        }

        @Override
        public boolean bSeen() {
            this.update();
            return (this.vis & 1) != 0;
        }

        @Override
        public boolean bCanSee() {
            this.update();
            return (this.vis & 2) != 0;
        }

        @Override
        public boolean bCouldSee() {
            this.update();
            return (this.vis & 4) != 0;
        }

        @Override
        public float darkMulti() {
            return this.cacheDarkMulti;
        }

        @Override
        public float targetDarkMulti() {
            return this.cacheTargetDarkMulti;
        }

        @Override
        public ColorInfo lightInfo() {
            this.update();
            return this.lightInfo;
        }

        @Override
        public void lightverts(int i, int value) {
            throw new IllegalStateException();
        }

        @Override
        public void lampostTotalR(float r) {
            throw new IllegalStateException();
        }

        @Override
        public void lampostTotalG(float g) {
            throw new IllegalStateException();
        }

        @Override
        public void lampostTotalB(float b) {
            throw new IllegalStateException();
        }

        @Override
        public void bSeen(boolean seen) {
            throw new IllegalStateException();
        }

        @Override
        public void bCanSee(boolean canSee) {
            throw new IllegalStateException();
        }

        @Override
        public void bCouldSee(boolean couldSee) {
            throw new IllegalStateException();
        }

        @Override
        public void darkMulti(float f) {
            throw new IllegalStateException();
        }

        @Override
        public void targetDarkMulti(float f) {
            throw new IllegalStateException();
        }

        @Override
        public int resultLightCount() {
            return this.lightsCount;
        }

        @Override
        public IsoGridSquare.ResultLight getResultLight(int index) {
            return this.lights[index];
        }

        @Override
        public void reset() {
            this.updateTick = -1;
        }

        private void update() {
            if (LightingJNI.updateCounter[this.playerIndex] != -1) {
                if (this.updateTick != LightingJNI.updateCounter[this.playerIndex]
                    && LightingJNI.getSquareLighting(this.playerIndex, this.square.x, this.square.y, this.square.z, lightInts)) {
                    IsoPlayer isoPlayer = IsoPlayer.players[this.playerIndex];
                    boolean boolean0 = (this.vis & 1) != 0;
                    int int0 = 0;
                    this.vis = (byte)(lightInts[int0++] & 7);
                    this.lightInfo.r = (float)(lightInts[int0] & 0xFF) / 255.0F;
                    this.lightInfo.g = (float)(lightInts[int0] >> 8 & 0xFF) / 255.0F;
                    this.lightInfo.b = (float)(lightInts[int0++] >> 16 & 0xFF) / 255.0F;
                    this.cacheDarkMulti = (float)lightInts[int0++] / 100000.0F;
                    this.cacheTargetDarkMulti = (float)lightInts[int0++] / 100000.0F;
                    float float0 = 1.0F;
                    float float1 = 1.0F;
                    if (isoPlayer != null) {
                        int int1 = this.square.z - (int)isoPlayer.z;
                        if (int1 == -1) {
                            float0 = 1.0F;
                            float1 = 0.85F;
                        } else if (int1 < -1) {
                            float0 = 0.85F;
                            float1 = 0.85F;
                        }

                        if ((this.vis & 2) == 0 && (this.vis & 4) != 0) {
                            int int2 = (int)isoPlayer.x;
                            int int3 = (int)isoPlayer.y;
                            int int4 = this.square.x - int2;
                            int int5 = this.square.y - int3;
                            if (isoPlayer.dir != IsoDirections.Max && Math.abs(int4) <= 2 && Math.abs(int5) <= 2) {
                                int[] int6 = LightingJNI.ForcedVis[isoPlayer.dir.index()];

                                for (byte _byte = 0; _byte < int6.length; _byte += 2) {
                                    if (int4 == int6[_byte] && int5 == int6[_byte + 1]) {
                                        this.vis = (byte)(this.vis | 2);
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    for (int int7 = 0; int7 < 4; int7++) {
                        int int8 = lightInts[int0++];
                        float float2 = (float)(int8 & 0xFF) * float1;
                        float float3 = (float)((int8 & 0xFF00) >> 8) * float1;
                        float float4 = (float)((int8 & 0xFF0000) >> 16) * float1;
                        this.cacheVertLight[int7] = (int)float2 << 0 | (int)float3 << 8 | (int)float4 << 16 | 0xFF000000;
                    }

                    for (int int9 = 4; int9 < 8; int9++) {
                        int int10 = lightInts[int0++];
                        float float5 = (float)(int10 & 0xFF) * float0;
                        float float6 = (float)((int10 & 0xFF00) >> 8) * float0;
                        float float7 = (float)((int10 & 0xFF0000) >> 16) * float0;
                        this.cacheVertLight[int9] = (int)float5 << 0 | (int)float6 << 8 | (int)float7 << 16 | 0xFF000000;
                    }

                    this.lightsCount = lightInts[int0++];

                    for (int int11 = 0; int11 < this.lightsCount; int11++) {
                        if (this.lights == null) {
                            this.lights = new IsoGridSquare.ResultLight[5];
                        }

                        if (this.lights[int11] == null) {
                            this.lights[int11] = new IsoGridSquare.ResultLight();
                        }

                        this.lights[int11].id = lightInts[int0++];
                        this.lights[int11].x = lightInts[int0++];
                        this.lights[int11].y = lightInts[int0++];
                        this.lights[int11].z = lightInts[int0++];
                        this.lights[int11].radius = lightInts[int0++];
                        int int12 = lightInts[int0++];
                        this.lights[int11].r = (float)(int12 & 0xFF) / 255.0F;
                        this.lights[int11].g = (float)(int12 >> 8 & 0xFF) / 255.0F;
                        this.lights[int11].b = (float)(int12 >> 16 & 0xFF) / 255.0F;
                        this.lights[int11].flags = int12 >> 24 & 0xFF;
                    }

                    this.updateTick = LightingJNI.updateCounter[this.playerIndex];
                    if ((this.vis & 1) != 0) {
                        if (boolean0 && this.square.getRoom() != null && this.square.getRoom().def != null && !this.square.getRoom().def.bExplored) {
                            boolean boolean1 = true;
                        }

                        this.square.checkRoomSeen(this.playerIndex);
                        if (!boolean0) {
                            assert !GameServer.bServer;

                            if (!GameClient.bClient) {
                                Meta.instance.dealWithSquareSeen(this.square);
                            }
                        }
                    }
                }
            }
        }
    }
}
